<template>
  <view class="search-combox" :class="border ? '' : 'search-combox__no-border'">
    <view v-if="label" class="search-combox__label" :style="labelStyle">
      <text v-text="label"></text>
    </view>
    <view class="search-combox__input-box">
      <input
          class="search-combox__input"
          type="text"
          :placeholder="placeholder"
          placeholder-class="search-combox__input-plac"
          v-model="inputVal"
          @input="onInput"
          @focus="onFocus"
          @blur="onBlur"
          @keydown.enter="onEnter"
          @keydown.down="onArrowDown"
          @keydown.up="onArrowUp"
      />
      <uni-icons
          :type="showSelector ? 'top' : 'bottom'"
          size="14"
          color="#999"
          @click="toggleSelector"
      ></uni-icons>
    </view>
    <view class="search-combox__selector" v-if="showSelector">
      <view class="uni-popper__arrow"></view>
      <scroll-view scroll-y="true" class="search-combox__selector-scroll">
        <!-- 空列表提示 -->
        <view v-if="filterCandidatesLength === 0" class="search-combox__selector-empty">
          <text>{{ emptyTips }}</text>
        </view>
        <!-- 候选项 -->
        <view
            v-for="(item, index) in filterCandidates"
            :key="index"
            class="search-combox__selector-item"
            @click="onSelectorClick(index)"
            :class="{ active: index === activeIndex }"
            ref="selectorItems"
        >
          <text
              :style="
              matchIndex === index
                ? `font-weight: bold; background-color: ${selectedBackground}; color: ${selectedColor}`
                : ''
            "
          >
            {{
              item[keyName]
                  ? item[keyName].length > 16
                      ? item[keyName].substring(0, 16) + "..."
                      : item[keyName]
                  : item[keyName]
            }}
          </text>
        </view>
      </scroll-view>
    </view>
  </view>
</template>

<script>
export default {
  name: "BiSearchCombox",
  emits: ["input", "update:modelValue", "select"],
  props: {
    isJSON: {
      type: Boolean,
      default: false
    },
    keyName: {
      type: String,
      default: ""
    },
    selectedBackground: {
      type: String,
      default: "#e5e5e5"
    },
    selectedColor: {
      type: String,
      default: "#409eff"
    },
    border: {
      type: Boolean,
      default: true
    },
    label: {
      type: String,
      default: ""
    },
    labelWidth: {
      type: String,
      default: "auto"
    },
    placeholder: {
      type: String,
      default: ""
    },
    candidates: {
      type: Array,
      default() {
        return [];
      }
    },
    emptyTips: {
      type: String,
      default: "无匹配项"
    },
    // #ifndef VUE3
    value: {
      type: [String, Number],
      default: ""
    },
    // #endif
    // #ifdef VUE3
    modelValue: {
      type: [String, Number],
      default: ""
    },
    // #endif
  },
  data() {
    return {
      isInput: false,
      showSelector: false,
      inputVal: "",
      activeIndex: -1,
      matchIndex: -1
    };
  },
  computed: {
    labelStyle() {
      if (this.labelWidth === "auto") {
        return "";
      }
      return `width: ${this.labelWidth}`;
    },
    filterCandidates() {
      if (this.isInput) {
        if (this.isJSON) {
          return this.candidates.filter((item) => {
            return item[this.keyName]?.toString().includes(this.inputVal);
          });
        } else {
          return this.candidates.filter((item) => {
            return item.toString().includes(this.inputVal);
          });
        }
      } else {
        return this.candidates;
      }
    },
    filterCandidatesLength() {
      return this.filterCandidates.length;
    }
  },
  watch: {
    // #ifndef VUE3
    value: {
      handler(newVal) {
        this.inputVal = newVal;
        this.isInput = true;
        this.matchIndex = this.filterCandidates.findIndex((item) => {
          return this.isJSON ? item[this.keyName] === newVal : item === newVal;
        });
      },
      immediate: true
    },
    // #endif
    // #ifdef VUE3
    modelValue: {
      handler(newVal) {
        this.inputVal = newVal;
        this.isInput = true;
        this.matchIndex = this.filterCandidates.findIndex((item) => {
          return this.isJSON ? item[this.keyName] === newVal : item === newVal;
        });
      },
      immediate: true
    },
    // #endif
    inputVal() {
      this.matchIndex = this.filterCandidates.findIndex((item) => {
        return this.isJSON ? item[this.keyName] === this.inputVal : item === this.inputVal;
      });
    }
  },
  methods: {
    toggleSelector() {
      this.showSelector = !this.showSelector;
      this.isInput = false;
    },
    onFocus() {
      this.showSelector = true;
      this.isInput = false;
    },
    onBlur() {
      setTimeout(() => {
        this.showSelector = false;
        this.activeIndex = -1;
      }, 1000); // 延长隐藏时间
    },
    onInput() {
      this.showSelector = true;
      setTimeout(() => {
        this.$emit("input", this.inputVal);
        this.$emit("update:modelValue", this.inputVal);
      });
    },
    onSelectorClick(index) {
      const item = this.filterCandidates[index];
      if (this.isJSON) {
        this.inputVal = item[this.keyName];
      } else {
        this.inputVal = item;
      }
      this.showSelector = false;
      this.$emit("input", this.inputVal);
      this.$emit("update:modelValue", this.inputVal);
      this.$emit("select", item);
    },
    // 键盘支持
    onArrowDown(e) {
      if (!this.showSelector) return;
      this.activeIndex = Math.min(this.activeIndex + 1, this.filterCandidates.length - 1);
      this.scrollToActive();
    },
    onArrowUp(e) {
      if (!this.showSelector) return;
      this.activeIndex = Math.max(this.activeIndex - 1, 0);
      this.scrollToActive();
    },
    onEnter(e) {
      if (this.activeIndex >= 0 && this.showSelector) {
        this.onSelectorClick(this.activeIndex);
      }
    },
    scrollToActive() {
      const item = this.$refs.selectorItems?.[this.activeIndex];
      if (item) {
        item.scrollIntoView({ behavior: "smooth", block: "nearest" });
      }
    }
  }
};
</script>

<style lang="scss" scoped>
.search-combox__selector-item.active {
  background-color: #f5f7fa;
}
</style>

<style lang="scss" scoped>
.search-combox {
  font-family: "Segoe UI", sans-serif;
}

.search-combox__input-box {
  position: relative;
  display: flex;
  align-items: center;
  border-radius: 6px;
}

.search-combox__input {
  flex: 1;
  padding: 10px 12px;
  border: 1px solid #dcdcdc;
  border-radius: 6px;
  outline: none;
  transition: border-color 0.3s ease;
}

.search-combox__input:focus {
  border-color: #409eff;
  box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2);
}

.search-combox__selector {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  width: 100%;
  max-height: 240px;
  background-color: #fff;
  border: 1px solid #dcdcdc;
  border-radius: 8px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  z-index: 9999;
  overflow: hidden;
  animation: fadeIn 0.2s ease-in-out;
}

@keyframes fadeIn {
  from {
    opacity: 0;
    transform: translateY(-5px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.search-combox__selector-scroll {
  max-height: 220px;
  overflow-y: auto;
}

.search-combox__selector-item {
  padding: 10px 16px;
  cursor: pointer;
  transition: background-color 0.2s ease;
  display: flex;
  align-items: center;
  font-size: 14px;
}

.search-combox__selector-item:hover,
.search-combox__selector-item.active {
  background-color: #f5f7fa;
}

.search-combox__selector-item.active {
  color: #409eff;
  font-weight: 600;
}

.search-combox__selector-item text {
  width: 100%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.search-combox__selector-empty {
  padding: 16px;
  text-align: center;
  color: #999;
  font-style: italic;
}

// 自定义滚动条样式（仅支持 Web）
::-webkit-scrollbar {
  width: 6px;
}

::-webkit-scrollbar-track {
  background: #f1f1f1;
}

::-webkit-scrollbar-thumb {
  background: #ddd;
  border-radius: 3px;
}

::-webkit-scrollbar-thumb:hover {
  background: #ccc;
}

// 指向箭头美化
.uni-popper__arrow {
  border-bottom-color: #fff;
  z-index: 10;
}

.uni-popper__arrow::after {
  border-bottom-color: #dcdcdc;
}
</style>

